package com.application.Tree;

import it.unipr.ce.dsg.s2p.sip.Address;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Currency;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.application.Controller.NetworkController;
import com.application.Controller.ReadWriteFileController;
import com.application.PhanQuyen.Quyen;


import ReadWriteXML.CMember;
import ReadWriteXML.ReadXML;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.CountDownTimer;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;


public class BoardView extends SurfaceView implements SurfaceHolder.Callback {
	public static float horizontal = 100;
	public static float vertical = 50;
	public static int T_MOVE = 1;
	public static int T_NEW = 2;
	public static int T_UPDATE = 3;
	private SurfaceHolder holder;
	public BoardLoopThread loopThread;
	private TreeNode tree;
	TreeMenu tMenu;
	DetailNode detail = new DetailNode();
	public int control = T_MOVE;
	float xDown = -1, yDown = -1, xUp = -1, yUp = -1, x = -1, y = -1;
	private boolean isNew = false;
	private TreeNode cNode = null;
	private TreeNode newNode = null;
	long downTime = 0, longTime = 0, upTime = 0, tempTime = 0;
	private boolean isTouchUp = false, isTouchDown = false;
	long id = 1;
	int cId = -1;
	private ArrayList<TreeNode> list = new ArrayList<TreeNode>();
	private Bitmap background;
	public static String treePath = Environment.getExternalStorageDirectory()
			+ "/" + "tree.xml";
	public static boolean isActive = false;
	private long pID;

	public BoardView(Context context) {
		super(context);
		init();
	}

	public BoardView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public BoardView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}
 
	private void init() {
		isActive = true;
//		int h = MESApplication.getHeight();
//		int w = MESApplication.getWidth();
		getHolder().addCallback(this);
		loopThread = new BoardLoopThread(this);
//		tree = new TreeNode(1, "[Tiêu đề]", "[Node gốc]", w / 2, h / 2, "phu");
		if(!ReadWriteFileController.isFile(treePath)){
			//Log.d("Phu","create Root");
			tree=createRoot();
			tree.writeXML(treePath);
		}
		else{
			Log.d("Phu","doc tu file");
			readXml(treePath);
		}
//		Log.d("Phu", "Node goc text:" + tree.getText());
		// background =
		// BitmapFactory.decodeResource(getResources(),R.drawable.boardview_bg);

		TreeNode c11 = new TreeNode(11, "11", "11", 0, 0, "phu");
		TreeNode c111 = new TreeNode(111, "111", "111", 0, 0, "phu");
		TreeNode c112 = new TreeNode(112, "112", "112", 0, 0, "phu");

		TreeNode c1111 = new TreeNode(1111, "1111", "1111", 0, 0, "phu");
		c111.add(c1111);

		c11.add(c111);
		c11.add(c112);

		TreeNode c12 = new TreeNode(12, "12", "12", 0, 0, "phu");
		// tree.add(c12);
		// tree.add(c11);
		// tMenu=new TreeMenu();
		// tMenu.x=-w/2;
		this.control = T_MOVE;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		if(canvas==null){
			return;
		}
		canvas.drawColor(Color.rgb(183, 222, 232));
		// canvas.drawBitmap(background, 0,0, null);
		tree.onDraw(canvas);
		// tMenu.onDraw(canvas);
		detail.onDraw(canvas);

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int action = event.getAction() & MotionEvent.ACTION_MASK;
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			touchDown(event.getX(), event.getY());
			break;
		case MotionEvent.ACTION_MOVE:
			touchMove(event.getX(), event.getY());
			break;
		case MotionEvent.ACTION_UP:
			touchUp(event.getX(), event.getY());
			break;
		case MotionEvent.ACTION_POINTER_DOWN:

			break;
		default:
			break;
		}
		return true;
	}

	private void touchDown(float x, float y) {
		this.isTouchUp = false;
		this.isTouchDown = true;
		downTime = System.currentTimeMillis();
		control = T_MOVE;
		INode collistionNode = tree.getCollision(x, y);
		if (collistionNode != null) {
			cNode = (TreeNode) collistionNode;
			cId = (int) collistionNode.id;
		} else {
			cNode = null;
			cId = -1;
		}
		if (downTime - tempTime < 400) {
			if (cNode != null && cId != -1)
				control = T_UPDATE;

		}
		final float _x = x, _y = y;
		CountDownTimer count = new CountDownTimer(1000, 100) {
			boolean moved = false;

			@Override
			public void onTick(long millisUntilFinished) {
				if (BoardView.this.x - _x > 10 || BoardView.this.y - _y > 10) {
					moved = true;
				}
			}

			@Override
			public void onFinish() {
				if (!moved && !isTouchUp) {

					if (cNode != null && cId != -1) {
						pID = cNode.getId();

						newNode = new TreeNode(NetworkController.getPersonID(),
								"[Tiêu đề]", "[Mới thêm]", _x, _y,
								NetworkController._peer.getAccount()
										.get_Username());
						Log.d("Phu", "tao node moi :pid=" + pID + " id="
								+ newNode.getId());
						cNode.add(newNode);
						cNode = newNode;

						control = T_NEW;
					}
				}
			}
		}.start();
		this.xDown = x;
		this.yDown = y;
		this.x = x;
		this.y = y;
	}

	private void touchUp(float x, float y) {
		tempTime = downTime;
		//Log.d("Phu", "detail " + (System.currentTimeMillis() - downTime));
		if (System.currentTimeMillis() - downTime < 200) {
			detail = new DetailNode(cNode);
		}
		if (control == T_UPDATE) {
			AlertDialog.Builder alert = new AlertDialog.Builder(
					this.getContext());
			final EditText input = new EditText(this.getContext());
			input.setText(cNode.text);
			alert.setTitle("Nhập nội dung!");
			alert.setView(input);
			alert.setPositiveButton("Cập nhật",
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							cNode.setText(input.getText().toString());

							ArrayList<CMember> members = ReadWriteFileController
									.readMember(ReadWriteFileController.MEMBER_PATH);
							for (CMember m : members) {
								NetworkController.sendUpdateNodeText(
										new Address(m.get_ip()), cNode.getId(),
										cNode.getText());

							}
						}
					});
			alert.setNegativeButton("Sắp xếp",
					new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							cNode.autoArrange();
						}
					});
			alert.setNeutralButton("Xóa node này",
					new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {

							boolean delete = true;
							Quyen q = NetworkController._peer.getAccount().getRuleById(17);
							String loi = "";

							// Kiểm tra có quyền xóa node ko?
							if (q == null
									|| (q != null && q.getSend() == false)) {
								delete = false;
								loi = "Bạn không có quyền xóa!";
								// Tìm xem node có node con của người khác ko
								if (cNode.getUser() == NetworkController._peer
										.getAccount().get_Username()) {
									boolean haveChildren = cNode
											.haveOtherChildren(NetworkController._peer
													.getAccount()
													.get_Username());
									if (haveChildren) {
										delete = false;
										loi = "Không thể xóa khi có ý kiến của người khác!";
									} else {
										delete = true;
									}
								} else {
									delete = false;
									loi = "Không thể xóa ý kiến của người khác!";
								}
							}

							if (delete) {
								Toast.makeText(getContext(),
										"Xoa node co id=" + cNode.id, 1).show();
								tree.remove(cNode);
								// Gửi thông tin cho các thành viên
								ArrayList<CMember> members = ReadWriteFileController
										.readMember(ReadWriteFileController.MEMBER_PATH);
								for (CMember m : members) {
									NetworkController.sendDeleteTreeNode(
											new Address(m.get_ip()),
											cNode.getId());

								}
							} else {
								Toast.makeText(getContext(), loi,
										Toast.LENGTH_SHORT).show();
							}
						}
					});
			alert.show();

		} else if (control == T_NEW) {
			final MyDialog dialog = new MyDialog(getContext(), "Tạo node mới!");

			dialog.show();
			//Log.d("Phu", "ok click:" + dialog.isOkClick());
			dialog.setOKClickListener(new MyHandlerInterface() {

				@Override
				public void onHandle(Object obj) {
					newNode.setBgColor(dialog.getColor());
					newNode.setText(dialog.getText());
					newNode.setTitle(dialog.getTextTitle());
					newNode.setBgColor(dialog.getColor());

					// Gửi thông tin cho các thành viên
					ArrayList<CMember> members = ReadWriteFileController
							.readMember(ReadWriteFileController.MEMBER_PATH);
					for (CMember m : members) {
						NetworkController.sendAddTreeNode(
								new Address(m.get_ip()), pID, newNode);

					}
				}
			});
			dialog.setCancelClickListener(new MyHandlerInterface() {

				@Override
				public void onHandle(Object obj) {
					tree.remove(newNode);
				}
			});

		}
		cId = -1;
		this.isTouchUp = true;
		this.isTouchDown = false;
		xUp = x;
		yUp = y;
		this.x = x;
		this.y = y;
		control = -1;
		upTime = System.currentTimeMillis();
	}

	private void touchMove(float x, float y) {
		float moveX, moveY, kcX, kcY;
		if (control == T_NEW && newNode != null)
			newNode.setPostion(x, y);
		else if (control == T_MOVE) {
			moveX = x - this.x;
			moveY = y - this.y;
			if (cId != -1 && cNode != null) {

				// cNode.setPostion(cNode.x + moveX, cNode.y + moveY);
				cNode.moveAll(moveX, moveY);
				if (detail != null && detail.node == cNode) {
					detail.moveAll(moveX, moveY);
				}

			} else {
				tree.moveAll(moveX, moveY);
				if (detail != null) {
					detail.moveAll(moveX, moveY);
				}
			}

		}
		this.x = x;
		this.y = y;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// this.setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
	}

	public void setTool(int tool) {
		this.control = tool;
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub

	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		//	Log.d("Phu", "surfaceCreated BoardView ");

		if (loopThread.getState() == Thread.State.TERMINATED) {
			loopThread = new BoardLoopThread(this);
			loopThread.setRunning(true);
			loopThread.start();
		} else {
			loopThread.setRunning(true);
			loopThread.start();
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		isActive = false;
		//Log.d("Phu", "surfaceDestroyed BoardView");
		boolean retry = true;
		loopThread.setRunning(false);
		while (retry) {
			try {
				loopThread.join();
				retry = false;
			} catch (InterruptedException e) {

			}
		}
	}

	public void removeNode(TreeNode node) {	
		tree.remove(node);
	}

	public void removeNode(TreeNode node, String path) {
		tree.remove(node);
		writeXML(path);
	}

	public void removeNodeByID(long id) {
		INode n = tree.getById(id);
		tree.remove(n);
	}

	public void removeNodeById(long id, String path) {
		if (isActive) {
			removeNodeByID(id);
		} else {
			this.readXml(path);
			this.removeNodeByID(id);
			writeXML(path);
		}
	}

	public void sapXepCay(TreeNode node) {
		// int id = node.getId();
		// ArrayList<TreeNode> children = new ArrayList<TreeNode>();
		// for (int i = 0; i < listNode.size(); i++) {
		// if (listNode.get(i).getParentNode() != null &&
		// listNode.get(i).getParentNode().getId() == id) {
		// children.add(listNode.get(i));
		// }
		// }
		// float firstX = node.getX() + TreeNode.width;
		// // firstX-=horizontal*children.size();
		// firstX -= TreeNode.width * children.size();
		// if (children.size() > 2)
		// firstX /= 2;
		// float firstY = node.getY() + TreeNode.heigh + vertical;
		// for (int i = 0; i < children.size(); i++) {
		// children.get(i).setX(firstX + i * (TreeNode.width) + TreeNode.width /
		// 2);
		// children.get(i).setY(firstY);
		// sapXepCay(children.get(i));
		// }
	}

	public void writeXML(String path) {
		tree.writeXML(path);
		//	Log.d("Phu", "Boardview.writeXML: Da ghi cay xuong file:" + path);
	}

	public void readXml(String path) {
		Document doc = ReadXML.BuildXML(path);
		tree = new TreeNode();
		tree.readXML((Element) doc.getFirstChild().getFirstChild());
		//	Log.d("Phu","Đã đọc cây từ file lên: số node con="+tree.getChildren().size());
	}

	public void addNode(long idParent, INode node) {
		//	Log.d("Phu", "BoardView.addNode: pid=" + idParent);
		INode p = tree.getById(idParent);
		//	Log.d("Phu", "BoardView.addNode " + (p == null));
		if (p != null) {
			//	Log.d("Phu", "da add: pid=" + idParent);
			p.add(node);
		}
	}

	public void addNode(long idParent, INode node, String path) {
		//	Log.d("Phu", "Boardview.addNode:" + path);
		if (!isActive) {
			this.readXml(path);
			INode p = tree.getById(idParent);
			if (p != null)
				p.add(node);
			writeXML(path);
		} else {
			addNode(idParent, node);
		}

	}

	public void updateText(long id, String text, String path) {
		if (!isActive) {
			this.readXml(path);
			INode node = tree.getById(id);
			if (node != null) {
				node.setText(text);
			}
			writeXML(path);
		} else {
			INode node = tree.getById(id);
			if (node != null) {
				node.setText(text);
			}
		}
	}

	public void zoomIn() {
		tree.zoomIn();
	}

	public TreeNode getTree() {
		return tree;
	}

	public static TreeNode createRoot(){
		TreeNode rs=new TreeNode(1, "[]", "", 0, 0, "[Hệ thống]");
		rs.writeXML(treePath);
		return rs;
	}
}
